#include "utils/strategy_base.h"
#include <arpa/inet.h>
#include <atomic>
#include <chrono>
#include <cstring>
#include <dlfcn.h>
#include <fcntl.h>
#include <fstream>
#include <iostream>
#include <memory>
#include <mutex>
#include <netinet/in.h>
#include <sstream>
#include <sys/mman.h>
#include <sys/socket.h>
#include <thread>
#include <unistd.h>
#include <vector>

#define PORT 10086
#define BUFFER_SIZE 1024

class StrategyEngine {
public:
  explicit StrategyEngine(const std::string &shm_name) : shm_name(shm_name) {
    // 打开共享内存
    shm_fd = shm_open(shm_name.c_str(), O_RDWR, 0666);
    if (shm_fd == -1) {
      perror("shm_open");
      exit(EXIT_FAILURE);
    }

    // 映射共享内存
    void *addr =
        mmap(nullptr, sizeof(ShmHeader) + BUFFER_CAPACITY * sizeof(Tick),
             PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
    if (addr == MAP_FAILED) {
      perror("mmap");
      exit(EXIT_FAILURE);
    }

    header = reinterpret_cast<ShmHeader *>(addr);
    buffer = reinterpret_cast<Tick *>(reinterpret_cast<char *>(header) +
                                      sizeof(ShmHeader));
  }

  ~StrategyEngine() {
    // 清理
    if (munmap(reinterpret_cast<char *>(header),
               sizeof(ShmHeader) + BUFFER_CAPACITY * sizeof(Tick)) == -1) {
      perror("munmap");
    }
    if (close(shm_fd) == -1) {
      perror("close");
    }
  }

  void Run() {
    // 启动 socket 服务器线程
    std::thread(&StrategyEngine::StartSocketServer, this).detach();

    while (true) {
      // 等待可用数据
      if (sem_wait(&header->data_ready) == -1) {
        perror("sem_wait");
        break;
      }

      // 读取已提交数据
      size_t current_commit = header->commit.load(std::memory_order_acquire);
      size_t current_tail = header->tail.load(std::memory_order_relaxed);

      while (current_tail < current_commit) {
        const Tick &tick = buffer[current_tail % BUFFER_CAPACITY];
        ProcessTick(tick);
        current_tail++;
      }

      // 更新消费位置
      header->tail.store(current_tail, std::memory_order_release);
      sem_post(&header->space_available);
    }
  }

private:
  void ProcessTick(const Tick &tick) {
    // std::cout << "Process: " << tick.symbol << " Price: " << tick.price
    //           << " Seq: " << (tick.timestamp & 0xFFFF) << std::endl;

    // 分发行情数据给所有策略实例
    std::lock_guard<std::mutex> lock(mutex_);
    for (auto &instance : strategy_instances_) {
      instance->OnTick(tick);
    }
  }

  void StartSocketServer() {
    // 端口重用
    int server_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (server_fd == -1) {
      perror("socket");
      return;
    }

    // 设置 SO_REUSEADDR 选项
    int opt = 1;
    if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) <
        0) {
      perror("setsockopt");
      close(server_fd);
      return;
    }

    sockaddr_in address{};
    address.sin_family = AF_INET;
    address.sin_addr.s_addr = INADDR_ANY;
    address.sin_port = htons(PORT);

    if (bind(server_fd, reinterpret_cast<sockaddr *>(&address),
             sizeof(address)) == -1) {
      perror("bind");
      close(server_fd);
      return;
    }

    if (listen(server_fd, 5) == -1) {
      perror("listen");
      close(server_fd);
      return;
    }

    while (true) {
      int client_fd = accept(server_fd, nullptr, nullptr);
      if (client_fd == -1) {
        perror("accept");
        continue;
      }

      std::thread(&StrategyEngine::HandleClient, this, client_fd).detach();
    }

    close(server_fd);
  }

  void HandleClient(int client_fd) {
    char buffer[BUFFER_SIZE];
    ssize_t bytes_read = read(client_fd, buffer, BUFFER_SIZE - 1);
    if (bytes_read > 0) {
      buffer[bytes_read] = '\0';
      ParseCommand(buffer);
    }
    close(client_fd);
  }

  void ParseCommand(const std::string &command) {
    std::istringstream iss(command);
    std::string action, lib_name, instance_name;

    // 提取动作和库名称
    if (!(iss >> action >> lib_name)) {
      std::cerr << "Invalid command format" << std::endl;
      return;
    }

    // 提取所有实例名称
    std::vector<std::string> instance_names;
    while (iss >> instance_name) {
      instance_names.push_back(instance_name);
    }

    if (action == "start") { // 启动策略实例
      for (const auto &instance_name : instance_names) {
        std::string config_path =
            "conf/" + lib_name + "/" + instance_name + ".json";
        LoadStrategy(lib_name, instance_name, config_path);
      }
    } else if (action == "stop") { // 停止策略实例
      for (const auto &instance_name : instance_names) {
        StopStrategy(lib_name, instance_name);
      }
    } else {
      std::cerr << "Unknown action: " << action << std::endl;
    }
  }

  void LoadStrategy(const std::string &lib_name,
                    const std::string &instance_name,
                    const std::string &config_path) {
    std::lock_guard<std::mutex> lock(mutex_);

    void *handle = dlopen(("lib/lib" + lib_name + ".so").c_str(), RTLD_LAZY);
    if (!handle) {
      std::cerr << "dlopen failed: " << dlerror() << std::endl;
      return;
    }

    using CreateFactoryFunc = StrategyFactory *(*)();
    CreateFactoryFunc create_factory =
        reinterpret_cast<CreateFactoryFunc>(dlsym(handle, "CreateFactory"));
    if (!create_factory) {
      std::cerr << "dlsym failed: " << dlerror() << std::endl;
      dlclose(handle);
      return;
    }

    StrategyFactory *factory = create_factory();
    BaseStrategy *strategy = factory->CreateStrategy(config_path);
    strategy->SetBasicInfo(lib_name, instance_name);
    if (strategy) {
      strategy_instances_.emplace_back(strategy);
      std::cout << "Loaded strategy: " << lib_name
                << " instance: " << instance_name << std::endl;
    } else {
      std::cerr << "Failed to create strategy instance" << std::endl;
    }

    delete factory;
    dlclose(handle);
  }

  // 新增 StopStrategy 方法
  void StopStrategy(const std::string &lib_name,
                    const std::string &instance_name) {
    std::lock_guard<std::mutex> lock(mutex_);

    auto it =
        std::remove_if(strategy_instances_.begin(), strategy_instances_.end(),
                       [lib_name, instance_name](
                           const std::unique_ptr<BaseStrategy> &strategy) {
                         // 假设 BaseStrategy
                         // 提供了获取策略库名称和实例名称的方法
                         return (strategy->GetLibName() == lib_name &&
                                 strategy->GetInstanceName() == instance_name);
                       });

    if (it != strategy_instances_.end()) {
      strategy_instances_.erase(it, strategy_instances_.end());
      std::cout << "Stopped strategy: " << lib_name
                << " instance: " << instance_name << std::endl;
    } else {
      std::cerr << "Failed to find strategy instance to stop" << std::endl;
    }
  }

  std::string shm_name;
  int shm_fd;
  ShmHeader *header;
  Tick *buffer;
  std::vector<std::unique_ptr<BaseStrategy>> strategy_instances_;
  std::mutex mutex_;
};

int main(int argc, char *argv[]) {
  // if (argc != 2) {
  //   std::cerr << "Usage: " << argv[0] << " <shared_memory_name>" <<
  //   std::endl; return 1;
  // }

  // std::string shm_name = argv[1];
  StrategyEngine engine("/tick_ring_buffer");
  engine.Run();
  return 0;
}